package com.kakarote.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.*;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.TypeUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.google.common.collect.Lists;
import com.kakarote.admin.common.AdminCodeEnum;
import com.kakarote.admin.common.PwdUtil;
import com.kakarote.admin.entity.BO.*;
import com.kakarote.admin.entity.PO.*;
import com.kakarote.admin.entity.VO.*;
import com.kakarote.admin.mapper.AdminDeptMapper;
import com.kakarote.admin.mapper.AdminUserMapper;
import com.kakarote.admin.service.*;
import com.kakarote.common.log.entity.OperationLog;
import com.kakarote.common.log.enums.BehaviorEnum;
import com.kakarote.core.common.Const;
import com.kakarote.core.common.MultipartFileUtil;
import com.kakarote.core.common.Result;
import com.kakarote.core.common.cache.AdminCacheKey;
import com.kakarote.core.common.enums.BaseStatusEnum;
import com.kakarote.core.common.enums.FieldEnum;
import com.kakarote.core.common.enums.SystemCodeEnum;
import com.kakarote.core.entity.*;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.admin.entity.AdminUserInfo;
import com.kakarote.core.feign.admin.entity.SimpleDept;
import com.kakarote.core.feign.admin.entity.SimpleUser;
import com.kakarote.core.feign.admin.service.AdminFileService;
import com.kakarote.core.redis.Redis;
import com.kakarote.core.servlet.ApplicationContextHolder;
import com.kakarote.core.servlet.BaseServiceImpl;
import com.kakarote.core.utils.*;
import com.kakarote.hrm.feign.entity.HrmEmployee;
import com.kakarote.hrm.feign.service.HrmService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.ss.usermodel.*;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author zhangzhiwei
 * @since 2020-04-27
 */
@Service
public class AdminUserServiceImpl extends BaseServiceImpl<AdminUserMapper, AdminUser> implements IAdminUserService {

    @Resource IAdminRoleService adminRoleService;
    @Resource IAdminDeptService adminDeptService;
    @Resource IAdminUserConfigService adminUserConfigService;
    @Resource IAdminUserRoleService adminUserRoleService;
    @Resource IAdminDeptRoleService adminDeptRoleService;
    @Resource IAdminAttentionService adminAttentionService;
    @Resource IAdminSubsidiaryDeptService adminSubsidiaryDeptService;
    @Resource HrmService hrmService;
    @Resource AdminFileService adminFileService;
    @Resource Redis redis;
    @Resource IAdminCompanySecuritySettingService securitySettingService;
    @Resource IAdminUserPwdHistoryService pwdHistoryService;
    @Resource AdminDeptMapper adminDeptMapper;

    @Override
    public List<AdminUserInfo> findByUsername(String username, Long companyIdLogin, HttpServletRequest request) {
        String serverName = StrUtil.isNotEmpty(request.getHeader("proxyHost")) ? request.getHeader("proxyHost") : request.getServerName();
        log.info("当前请求域名：{}", serverName);
        List<AdminUserInfo> userInfoList = getBaseMapper().findByUsername(username);
        return setSuperInfo(userInfoList);
    }

    /**
     * 查询企业下所有用户
     * @param adminUserBO 业务对象
     * @return ids
     */
    @Override
    public BasePage<AdminUserVO> queryUserList(AdminUserBO adminUserBO) {
        BasePage<AdminUserVO> basePage = new BasePage<>();
        if (adminUserBO == null) {
            List<AdminUserVO> adminUserVOList = this.lambdaQuery().ne(AdminUser::getUserId, UserUtil.getSuperUser())
                    .list().stream().map(adminUser -> this.convertAdminUserToVo(adminUser, 2)).collect(Collectors.toList());
            //置顶超级管理员
            AdminUser adminSuperUser = this.getById(UserUtil.getSuperUser());
            adminUserVOList.add(0, this.convertAdminUserToVo(adminSuperUser, 0));
            basePage.setRecords(adminUserVOList);
        } else {
            Long deptOwnerUserId = null;
            adminUserBO.setUserId(UserUtil.getSuperUser());
            if(!UserUtil.isAdmin()){
                if(adminUserBO.getDeptId()==null) {
                    adminUserBO.setDeptId(UserUtil.getUser().getDeptId());
                }
                List<Long> list;
                if (Objects.equals(adminUserBO.getIsNeedChild(), 1)) {
                    list = adminDeptService.queryChildDept(adminUserBO.getDeptId());
                } else {
                    list = new ArrayList<>();
                }
                list.add(adminUserBO.getDeptId());
                adminUserBO.setDeptIdList(list);
                deptOwnerUserId = adminDeptService.getById(adminUserBO.getDeptId()).getOwnerUserId();
                adminUserBO.setDeptOwnerUserId(deptOwnerUserId);
            }

            basePage = getBaseMapper().queryUserList(adminUserBO.parse(), adminUserBO);
            LambdaQueryWrapper<AdminUserHisTable> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(AdminUserHisTable::getUserId);
            queryWrapper.eq(AdminUserHisTable::getHisTable, 1);
            List<Long> longs = ApplicationContextHolder.getBean(IAdminUserHisTableService.class).listObjs(queryWrapper, user -> Long.valueOf(user.toString()));
            for (AdminUserVO adminUserVO : basePage.getRecords()) {
                if (longs.contains(adminUserVO.getUserId())) {
                    adminUserVO.setHisTable(1);
                }
                List<AdminRole> adminRoleList = adminRoleService.queryRoleListByUserId(adminUserVO.getUserId());
                adminRoleList.removeIf(a -> a.getRoleType() == 8);
                adminUserVO.setRoleId(adminRoleList.stream().map(adminRole -> adminRole.getRoleId().toString()).collect(Collectors.joining(",")));
                adminUserVO.setRoleName(adminRoleList.stream().map(AdminRole::getRoleName).collect(Collectors.joining(",")));
                //标识超级管理员和部门负责人
                if (Objects.equals(adminUserVO.getUserId(), UserUtil.getSuperUser())) {
                    adminUserVO.setUserIdentity(0);
                }
                //既是主账号又是负责人以主账号为准
                if (Objects.equals(adminUserVO.getUserId(), deptOwnerUserId) && Objects.equals(2, adminUserVO.getUserIdentity())) {
                    adminUserVO.setUserIdentity(1);
                }
            }
            //按照是否负责人进行数据排序
            basePage.getList().sort(Comparator.comparing(AdminUserVO::getUserIdentity));
        }


        basePage.getList().forEach(adminUserVO -> {
            List<AdminSubsidiaryDept> subsidiaryDepts = adminSubsidiaryDeptService.lambdaQuery().eq(AdminSubsidiaryDept::getUserId, adminUserVO.getUserId()).list();

            List<Long> deptIds = subsidiaryDepts.stream().map(AdminSubsidiaryDept::getDeptId).collect(Collectors.toList());
            adminUserVO.setSubsidiaryDeptIds(deptIds);


            if (CollectionUtil.isNotEmpty(deptIds)) {
                QueryWrapper<AdminDept> deptQueryWrapper = new QueryWrapper<>();
                deptQueryWrapper.select("name")
                        .in("dept_id", deptIds);

                String deptNames = adminDeptService.listObjs(deptQueryWrapper, TypeUtils::castToString)
                        .stream()
                        .filter(Objects::nonNull)
                        .map(String::valueOf)
                        .filter(StrUtil::isNotEmpty)
                        .collect(Collectors.joining(Const.SEPARATOR));
                adminUserVO.setSubsidiaryDeptName(deptNames);
            }

        });


        return basePage;
    }

    private AdminUserVO convertAdminUserToVo(AdminUser adminUser, Integer userIdentity) {
        AdminUserVO userVO = BeanUtil.copyProperties(adminUser, AdminUserVO.class);
        userVO.setUserIdentity(userIdentity);
        userVO.setDeptName(UserCacheUtil.getDeptName(userVO.getDeptId()));
        return userVO;
    }


    @Override
    public JSONObject countUserByLabel() {
        JSONObject jsonObject = new JSONObject();
        List<AdminDept> adminDeptList = adminDeptMapper.queryDeptList();
        Long logicDeptId = adminDeptService.getLogicDeptId();
        List<AdminDeptVO> childListTree = RecursionUtil.getChildListTree(adminDeptList, "parentId", logicDeptId, "deptId", "children", AdminDeptVO.class);
        List<Long> adminDeptIds = ExtractUtils.extractField(childListTree, AdminDeptVO::getDeptId);
        Long deptId = UserUtil.getUser().getDeptId();
        adminDeptIds.add(deptId);
        jsonObject
                .fluentPut("allUserCount", getBaseMapper().countUserByLabel(0, null,adminDeptIds))
//                .fluentPut("addNewlyCount", getBaseMapper().countUserByLabel(1, null,adminDeptIds))
                .fluentPut("activateCount", getBaseMapper().countUserByLabel(null, 1,adminDeptIds))
                .fluentPut("inactiveCount", getBaseMapper().countUserByLabel(2, null,adminDeptIds))
                .fluentPut("disableCount", getBaseMapper().countUserByLabel(3, null,adminDeptIds));
//                .fluentPut("applyUserCount", getBaseMapper().countUserApply(2));
        return jsonObject;
    }

    /**
     * 查询该用户下级的用户
     *
     * @param userId 用户ID 0代表全部
     * @return data
     */
    @Override
    public List<Long> queryChildUserId(Long userId) {

        return RecursionUtil.getChildList(list(), "parentId", userId, "userId", "userId");
    }


    /**
     * 新增或修改用户
     *
     * @param adminUserVO data
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OperationLog setUser(AdminUserVO adminUserVO) {
        if (adminUserVO.getParentId() == null) {
            adminUserVO.setParentId(0L);
        }
        List<Long> userList = queryChildUserId(adminUserVO.getUserId());
        if (userList.contains(adminUserVO.getParentId())) {
            throw new CrmException(AdminCodeEnum.ADMIN_PARENT_USER_ERROR);
        }
        if (adminUserVO.getUserId().equals(adminUserVO.getParentId())) {
            throw new CrmException(AdminCodeEnum.ADMIN_PARENT_USER_ERROR1);
        }
        //用户姓名处理
//        boolean exists = lambdaQuery().eq(AdminUser::getRealname, adminUserVO.getRealname()).ne(AdminUser::getUserId, adminUserVO.getUserId()).exists();
//        if (exists) {
//            throw new CrmException(AdminCodeEnum.ADMIN_USER_REAL_NAME_EXIST_ERROR);
//        }
        AdminUser oldUser = getById(adminUserVO.getUserId());
        if (oldUser == null) {
            throw new CrmException();
        }
        //不修改用户名
        adminUserVO.setUsername(null);
        //不修改密码
        adminUserVO.setPassword(null);
        AdminUser adminUser = BeanUtil.copyProperties(adminUserVO, AdminUser.class);
        adminUserRoleService.saveByUserId(adminUserVO.getUserId(), true, StrUtil.splitTrim(adminUserVO.getRoleId(), Const.SEPARATOR));
        updateById(adminUser);
        adminSubsidiaryDeptService.lambdaUpdate().eq(AdminSubsidiaryDept::getUserId, adminUserVO.getUserId()).remove();


        if (CollectionUtil.isNotEmpty(adminUserVO.getSubsidiaryDeptIds())) {
            List<AdminSubsidiaryDept> subsidiaryDeptList = adminUserVO.getSubsidiaryDeptIds().stream().map(deptId -> {
                AdminSubsidiaryDept subsidiaryDept = new AdminSubsidiaryDept();
                subsidiaryDept.setUserId(adminUserVO.getUserId());
                subsidiaryDept.setDeptId(deptId);
                return subsidiaryDept;
            }).collect(Collectors.toList());
            adminSubsidiaryDeptService.saveBatch(subsidiaryDeptList);
        }


        Long key = adminUser.getUserId();
        redis.del(AdminCacheKey.USER_AUTH_CACHE_KET + key);
        //删除用户缓存
        UserCacheUtil.removeUserCache(key);

        OperationLog operationLog = new OperationLog();
        operationLog.setOperationInfo("编辑员工信息：" + adminUser.getRealname());
        operationLog.setOperationObject(adminUser.getUserId(), adminUser.getRealname());
        return operationLog;
    }

    @Override
    public List<OperationLog> setUserDept(AdminUserBO adminUserBO) {
        Long deptId = adminUserBO.getDeptId();
        List<Long> userIdList = adminUserBO.getUserIdList();
        if (CollUtil.isEmpty(userIdList) || deptId == null) {
            throw new CrmException();
        }
        AdminDept dept = adminDeptService.getById(deptId);
        if (dept == null) {
            throw new CrmException(AdminCodeEnum.ADMIN_DEPT_NOT_EXIST_ERROR);
        }
        this.lambdaUpdate().set(AdminUser::getDeptId, deptId).in(AdminUser::getUserId, userIdList).update();

        List<OperationLog> operationLogList = new ArrayList<>();

        for (Long userId : userIdList) {
            SimpleUser simpleUser = UserCacheUtil.getSimpleUser(userId);
            if (simpleUser != null) {
                OperationLog operationLog = new OperationLog();
                operationLog.setOperationInfo("为" + simpleUser.getRealname() + "将部门由" + simpleUser.getDeptName() + "重置为" + dept.getName());
                operationLog.setOperationObject(userId, simpleUser.getRealname());
                operationLogList.add(operationLog);
                simpleUser.setDeptId(deptId);
                simpleUser.setDeptName(dept.getName());
                //删除用户缓存
                UserCacheUtil.removeUserCache(userId);
            }
        }

        return operationLogList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject addUser(AdminUserVO adminUser) {
        if (adminUser.getParentId() == null) {
            adminUser.setParentId(0L);
        }
        if (StrUtil.length(adminUser.getPassword()) > 20) {
            throw new CrmException(AdminCodeEnum.ADMIN_PASSWORD_INTENSITY_ERROR);
        }
        boolean exists = lambdaQuery().eq(AdminUser::getUsername, adminUser.getUsername()).exists();
        if (exists) {
            throw new CrmException(AdminCodeEnum.ADMIN_USER_EXIST_ERROR);
        }
//        boolean nameExists = lambdaQuery().eq(AdminUser::getRealname, adminUser.getRealname()).exists();
//        if (nameExists) {
//            throw new CrmException(AdminCodeEnum.ADMIN_USER_REAL_NAME_EXIST_ERROR);
//        }
        //获取密码规则配置
        AdminCompanySecuritySettingVO securitySettingVO = securitySettingService.queryByConfigType(1);
        //密码强度校验
        PwdUtil.checkPwdReg(securitySettingVO.getPwdCharRequire(), adminUser.getPassword(), securitySettingVO.getMinimumPwdLen());
        String salt = IdUtil.fastSimpleUUID();
        AdminUser adminUserPO = BeanUtil.copyProperties(adminUser, AdminUser.class);
        adminUserPO.setCreateTime(LocalDateTimeUtil.now());
        adminUserPO.setNum(RandomUtil.randomNumbers(15));
        adminUserPO.setMobile(adminUserPO.getUsername());
        adminUserPO.setSalt(salt);
        String password = UserUtil.sign((adminUser.getUsername().trim() + adminUser.getPassword().trim()), salt);
        adminUserPO.setPassword(password);
        save(adminUserPO);

        if (ObjectUtil.isNotNull(securitySettingVO)) {
            Integer enforcePwdHistory = securitySettingVO.getEnforcePwdHistory();
            if (ObjectUtil.isNotNull(enforcePwdHistory) && enforcePwdHistory > 0) {
                //保存密码历史
                pwdHistoryService.save(new AdminUserPwdHistory().setUserId(adminUserPO.getUserId()).setPwdHistory(JSONObject.toJSONString(Arrays.asList(password))));
            }
        }
        adminUserConfigService.initUserConfig(adminUserPO.getUserId());
        if (StrUtil.isEmpty(adminUser.getRoleId())) {
            adminUserRoleService.saveByUserId(adminUserPO.getUserId());
        } else {
            adminUserRoleService.saveByUserId(adminUserPO.getUserId(), false, StrUtil.splitTrim(adminUser.getRoleId(), Const.SEPARATOR));
        }

        if (ObjectUtil.isNotEmpty(adminUser.getSubsidiaryDeptIds())) {
            List<AdminSubsidiaryDept> subsidiaryDeptList = new ArrayList<>();
            for (Long subsidiaryDeptId : adminUser.getSubsidiaryDeptIds()) {
                AdminSubsidiaryDept adminSubsidiaryDept = new AdminSubsidiaryDept();
                adminSubsidiaryDept.setUserId(adminUserPO.getUserId());
                adminSubsidiaryDept.setDeptId(subsidiaryDeptId);
                subsidiaryDeptList.add(adminSubsidiaryDept);
            }
            adminSubsidiaryDeptService.saveBatch(subsidiaryDeptList);
        }
        //删除用户缓存
        UserCacheUtil.removeUserCache(adminUserPO.getUserId());

        OperationLog operationLog = new OperationLog();
        operationLog.setOperationInfo("新建员工：" + adminUserPO.getRealname());
        operationLog.setOperationObject(adminUserPO.getUserId(), adminUserPO.getRealname());

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("user", adminUserPO);
        jsonObject.put("operationLog", operationLog);
        return jsonObject;
    }

    /**
     * 修改用户信息
     *
     * @param adminUser
     */
    @Override
    public void updateUser(AdminUser adminUser) {
        if (!UserUtil.getUser().getUsername().equals(adminUser.getUsername())) {
            throw new CrmException(AdminCodeEnum.ADMIN_USERNAME_EDIT_ERROR);
        }
        adminUser.setUserId(UserUtil.getUserId());
        boolean b = StrUtil.isNotEmpty(adminUser.getPassword());
        adminUser.setStatus(null);
        boolean update = updateById(adminUser);
        AdminUser user = getById(adminUser.getUserId());
        SimpleUser simpleUser = new SimpleUser(user.getUserId(), user.getImg(), user.getRealname(), user.getDeptId(), UserCacheUtil.getDeptName(user.getDeptId()));
        //删除用户缓存
        UserCacheUtil.removeUserCache(adminUser.getUserId());
        DiscoveryClient discoveryClient = ApplicationContextHolder.getBean(DiscoveryClient.class);
        if (b && update) {
            //查询企业安全配置（是否退出登录设备）
            AdminCompanySecuritySettingVO securitySettingVO = securitySettingService.queryByConfigType(1);
            if (ObjectUtil.equal(1, securitySettingVO.getChangePwdRule())) {
                UserUtil.userExit(adminUser.getUserId(), null);
            }
        }
    }

    /**
     * 修改用户账号功能
     *
     * @param id       用户ID
     * @param username 新的用户名
     * @param password 新的密码
     * @return 操作状态
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public OperationLog usernameEdit(Long id, String username, String password) {
        AdminUser adminUser = getById(id);
        if (adminUser == null) {
            throw new CrmException(AdminCodeEnum.ADMIN_USER_NOT_EXIST_ERROR);
        }
        //查密码规则配置
        AdminCompanySecuritySettingVO securitySettingVO = securitySettingService.queryByConfigTypeAndCompanyId(1);
        //校验强度校验
        PwdUtil.checkPwdReg(securitySettingVO.getPwdCharRequire(), password, securitySettingVO.getMinimumPwdLen());

        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject(adminUser.getUserId(), adminUser.getRealname());
        operationLog.setOperationInfo("为员工" + adminUser.getRealname() + "重置登录账号");


        if (adminUser.getUsername().equals(username)) {
            throw new CrmException(AdminCodeEnum.ADMIN_ACCOUNT_ERROR);
        }
        boolean exists = lambdaQuery().eq(AdminUser::getUsername, username).exists();
        if (exists) {
            throw new CrmException(AdminCodeEnum.ADMIN_PHONE_REGISTER_ERROR);
        }
        adminUser.setUsername(username);
        adminUser.setMobile(username);
        adminUser.setPassword(UserUtil.sign(username + password, adminUser.getSalt()));
        UserUtil.userExit(adminUser.getUserId(), null);
        updateById(adminUser);
        return operationLog;
    }

    /**
     * excel导入员工
     *
     * @param file file
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject excelImport(MultipartFile file) {
        List<List<Object>> errList = new ArrayList<>();
        String filePath = getFilePath(file);
        AtomicReference<Integer> num = new AtomicReference<>(0);
        ExcelUtil.readBySax(filePath, 0, (int sheetIndex, long rowIndex, List<Object> rowList) -> {
            if (rowIndex > 1) {
                num.getAndSet(num.get() + 1);
                if (StrUtil.isEmptyIfStr(rowList.get(0))) {
                    rowList.add(0, "用户名不能为空");
                    errList.add(rowList);
                    return;
                }
                if (StrUtil.isEmptyIfStr(rowList.get(1))) {
                    rowList.add(0, "密码不能为空");
                    errList.add(rowList);
                    return;
                }
                if (StrUtil.length(rowList.get(1).toString()) > 20) {
                    rowList.add(0, "密码长度最长不超过20位");
                    errList.add(rowList);
                    return;
                }

                int listIndexTwo = 2;
                if (StrUtil.isEmptyIfStr(rowList.get(listIndexTwo))) {
                    rowList.add(0, "姓名不能为空");
                    errList.add(rowList);
                    return;
                } else {
                    boolean exists = query().eq("realname", rowList.get(2).toString().trim()).exists();
                    if (exists) {
                        rowList.add(0, "姓名重复");
                        errList.add(rowList);
                        return;
                    }
                }
                String username = rowList.get(0).toString().trim();
                boolean exists = lambdaQuery().eq(AdminUser::getUsername, username).exists();
                if (exists) {
                    rowList.add(0, "手机号已存在");
                    errList.add(rowList);
                    return;
                }

                String phoneRegex = "^[1][3,4,5,6,7,8,9][0-9]{9}$";
                if (!ReUtil.isMatch(phoneRegex, username)) {
                    rowList.add(0, "手机号格式不正确");
                    errList.add(rowList);
                    return;
                }
                AdminUser adminUser = new AdminUser();
                int listSize = 6;
                if (rowList.size() < listSize) {
                    rowList.add(0, "部门不能为空");
                    errList.add(rowList);
                    return;
                }
                String deptNames = Optional.ofNullable(rowList.get(5)).orElse("").toString().trim();
                if (!StrUtil.isEmpty(deptNames)) {
                    String[] strArr = deptNames.split("/");
                    Long deptId = null;
                    for (int i = 0; i < strArr.length; i++) {
                        AdminDept dept;
                        if (i == 0) {
                            dept = adminDeptService.lambdaQuery().select(AdminDept::getDeptId)
                                    .eq(AdminDept::getName, strArr[0])
                                    .one();

                        } else {
                            dept = adminDeptService.lambdaQuery().select(AdminDept::getDeptId)
                                    .eq(AdminDept::getName, strArr[i]).eq(AdminDept::getParentId, deptId)
                                    .one();
                        }
                        if (dept == null) {
                            Integer a = i + 1;
                            rowList.add(0, a + "级部门不存在");
                            errList.add(rowList);
                            return;
                        }
                        deptId = dept.getDeptId();
                    }

                    if (deptId == null) {
                        rowList.add(0, "部门不存在");
                        errList.add(rowList);
                        return;
                    }
                    adminUser.setDeptId(deptId);

                } else {
                    rowList.add(0, "部门不能为空");
                    errList.add(rowList);
                    return;
                }

                String password = rowList.get(1).toString().trim();
                String realname = rowList.get(2).toString().trim();
                String sex = null;
                int listIndexThree = 3;
                if (rowList.get(listIndexThree) != null) {
                    sex = Optional.ofNullable(rowList.get(3)).orElse("").toString().trim();
                }

                String email = null;
                int listIndexFour = 4;
                if (rowList.get(listIndexFour) != null) {
                    email = Optional.ofNullable(rowList.get(4)).orElse("").toString().trim();
                }
                String post = null;
                int listIndexSix = 6;
                if (rowList.size() > listIndexSix) {
                    post = Optional.ofNullable(rowList.get(6)).orElse("").toString().trim();
                }
                String salt = IdUtil.fastSimpleUUID();
                adminUser.setUsername(username);
                adminUser.setPassword(UserUtil.sign((adminUser.getUsername().trim() + password.trim()), salt));
                adminUser.setSalt(salt);
                adminUser.setNum(RandomUtil.randomNumbers(15));
                adminUser.setCreateTime(LocalDateTimeUtil.now());
                adminUser.setRealname(realname);
                adminUser.setMobile(username);
                adminUser.setEmail(email);
                adminUser.setPost(post);
                adminUser.setStatus(0);
                if (StrUtil.isNotEmpty(sex)) {
                    String woman = "女";
                    if (woman.equals(sex)) {
                        adminUser.setSex(2);
                    } else {
                        adminUser.setSex(1);
                    }
                }
                save(adminUser);
                adminUserConfigService.initUserConfig(UserUtil.getUserId());
            } else {
                if (rowIndex == 1) {
                    rowList.add(0, "错误信息");
                }
                errList.add(Convert.toInt(rowIndex), rowList);
            }
        });
        FileUtil.del(filePath);
        JSONObject result = new JSONObject().fluentPut("totalSize", num.get()).fluentPut("errSize", 0);
        int listSize = 2;
        if (errList.size() > listSize) {
            File errFile = FileUtil.file("excelData/" + IdUtil.simpleUUID() + ".xlsx");
            BigExcelWriter writer = ExcelUtil.getBigWriter(errFile);
            // 取消数据的黑色边框以及数据左对齐
            CellStyle cellStyle = writer.getCellStyle();
            cellStyle.setFillBackgroundColor(IndexedColors.BLACK.getIndex());
            cellStyle.setBorderTop(BorderStyle.NONE);
            cellStyle.setBorderBottom(BorderStyle.NONE);
            cellStyle.setBorderLeft(BorderStyle.NONE);
            cellStyle.setBorderRight(BorderStyle.NONE);
            cellStyle.setAlignment(HorizontalAlignment.LEFT);
            Font defaultFont = writer.createFont();
            defaultFont.setFontHeightInPoints((short) 11);
            cellStyle.setFont(defaultFont);
            // 取消数字格式的数据的黑色边框以及数据左对齐
            CellStyle cellStyleForNumber = writer.getStyleSet().getCellStyleForNumber();
            cellStyleForNumber.setBorderTop(BorderStyle.NONE);
            cellStyleForNumber.setBorderBottom(BorderStyle.NONE);
            cellStyleForNumber.setBorderLeft(BorderStyle.NONE);
            cellStyleForNumber.setBorderRight(BorderStyle.NONE);
            cellStyleForNumber.setAlignment(HorizontalAlignment.LEFT);
            cellStyleForNumber.setFillBackgroundColor(IndexedColors.BLACK.getIndex());
            cellStyleForNumber.setFont(defaultFont);

            CellStyle textStyle = writer.getWorkbook().createCellStyle();
            DataFormat format = writer.getWorkbook().createDataFormat();
            textStyle.setDataFormat(format.getFormat("@"));

            writer.merge(errList.get(1).size() + 1, errList.get(0).get(0).toString().trim(), true);
            writer.getHeadCellStyle().setAlignment(HorizontalAlignment.LEFT);
            writer.getHeadCellStyle().setWrapText(true);
            Font headFont = writer.createFont();
            headFont.setFontHeightInPoints((short) 11);
            writer.getHeadCellStyle().setFont(headFont);
            writer.getHeadCellStyle().setFillPattern(FillPatternType.NO_FILL);
            writer.getOrCreateRow(0).setHeightInPoints(120);
            writer.setRowHeight(-1, 20);

            //writer.merge(6, "系统用户导入模板(*)为必填项");
            for (int i = 0; i < errList.get(1).size(); i++) {
                writer.getSheet().setDefaultColumnStyle(i, textStyle);
            }
            errList.remove(0);
            writer.write(errList);
            writer.close();
            //将错误信息的excel保存七天 604800 七天的秒数
            MultipartFile multipartFile = MultipartFileUtil.getMultipartFile(errFile);
            UploadEntity uploadEntity = adminFileService.uploadTempFile(multipartFile, IdUtil.simpleUUID()).getData();

            redis.setex(AdminCacheKey.UPLOAD_EXCEL_MESSAGE_PREFIX + "file:" + uploadEntity.getFileId(), 604800, uploadEntity.getPath());

            result.fluentPut("errSize", errList.size() - 1).fluentPut("token", uploadEntity.getFileId());

        }
        return result;
    }

    private String getFilePath(MultipartFile file) {
        String dirPath = FileUtil.getTmpDirPath();
        try {
            InputStream inputStream = file.getInputStream();
            File fromStream = FileUtil.writeFromStream(inputStream, dirPath + "/" + IdUtil.simpleUUID() + file.getOriginalFilename());
            return fromStream.getAbsolutePath();
        } catch (IOException e) {
            throw new CrmException(SystemCodeEnum.SYSTEM_UPLOAD_FILE_ERROR);
        }
    }

    /**
     * 设置状态
     *
     * @param adminUserStatusBO status
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<OperationLog> setUserStatus(AdminUserStatusBO adminUserStatusBO) {
        if (adminUserStatusBO.getIds().isEmpty()) {
            throw new CrmException();
        }
        List<OperationLog> operationLogList = new ArrayList<>();
        for (Long id : adminUserStatusBO.getIds()) {
            OperationLog operationLog = new OperationLog();
            AdminUser user = getById(id);
            operationLog.setOperationObject(user.getUserId(), user.getRealname());


            if (BaseStatusEnum.CLOSE.getStatus().equals(adminUserStatusBO.getStatus())) {
                if (id.equals(UserUtil.getSuperUser())) {
                    throw new CrmException(AdminCodeEnum.ADMIN_SUPER_USER_DISABLED_ERROR);
                }
                UserUtil.userExit(id, null);

                operationLog.setBehavior(BehaviorEnum.FORBID);
            } else if (BaseStatusEnum.OPEN.getStatus().equals(adminUserStatusBO.getStatus())) {
                boolean roleExists = adminUserRoleService.lambdaQuery().eq(AdminUserRole::getUserId, id).exists();
                if (!roleExists) {
                    throw new CrmException(AdminCodeEnum.ADMIN_USER_NOT_ROLE_ERROR);
                }
                AdminUser adminUser = getById(id);
                if (adminUser.getDeptId() == null) {
                    throw new CrmException(AdminCodeEnum.ADMIN_USER_NOT_DEPT_ERROR);
                }
                operationLog.setBehavior(BehaviorEnum.ACTIVE);
            }
            lambdaUpdate().set(AdminUser::getStatus, adminUserStatusBO.getStatus()).eq(AdminUser::getUserId, id).update();
            operationLog.setOperationInfo(operationLog.getBehavior().getName() + "了员工：" + user.getRealname());
            operationLogList.add(operationLog);
        }
        return operationLogList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<OperationLog> resetPassword(AdminUserStatusBO adminUserStatusBO) {
        if (StrUtil.length(adminUserStatusBO.getPassword()) > 20) {
            throw new CrmException(AdminCodeEnum.ADMIN_PASSWORD_INTENSITY_ERROR);
        }
        AdminCompanySecuritySettingVO securitySettingVO = securitySettingService.queryByConfigType(1);
        //密码强度校验
        PwdUtil.checkPwdReg(securitySettingVO.getPwdCharRequire(), adminUserStatusBO.getPassword(), securitySettingVO.getMinimumPwdLen());
        List<OperationLog> operationLogList = new ArrayList<>();
        for (Long id : adminUserStatusBO.getIds()) {
            AdminUser adminUser = getById(id);
            String password = UserUtil.sign(adminUser.getUsername() + adminUserStatusBO.getPassword(), adminUser.getSalt());
            //查用户历史密码记录
            AdminUserPwdHistory pwdHistoryEntity = pwdHistoryService.getById(id);
            if (ObjectUtil.isNull(pwdHistoryEntity)) {
                pwdHistoryEntity = new AdminUserPwdHistory();
                pwdHistoryEntity.setUserId(id);
                pwdHistoryService.save(pwdHistoryEntity);

            }
            if (checkPwdHistory(pwdHistoryEntity.getPwdHistory(), adminUser.getPassword(), password, securitySettingVO)) {
                throw new CrmException(AdminCodeEnum.ADMIN_PASSWORD_CHANGE_ERROR);
            }
            String pwdHistory = handlePwdHistory(adminUser.getPassword(), pwdHistoryEntity.getPwdHistory(), password, securitySettingVO);
            pwdHistoryEntity.setPwdHistory(pwdHistory);
            pwdHistoryService.updateById(pwdHistoryEntity);
            lambdaUpdate().set(AdminUser::getPassword, password).set(AdminUser::getPwdUpdStatus, 1).eq(AdminUser::getUserId, id).update();
            if (ObjectUtil.equal(1, securitySettingVO.getChangePwdRule())) {
                UserUtil.userExit(adminUser.getUserId(), null);
            }
            OperationLog operationLog = new OperationLog();
            operationLog.setOperationObject(adminUser.getUserId(), adminUser.getRealname());
            operationLog.setOperationInfo("重置了员工" + adminUser.getRealname() + "的密码");
            operationLogList.add(operationLog);
        }
        return operationLogList;
    }

    /**
     * 根据用户ID查询角色ID
     *
     * @param userId userId
     * @return ids
     */
    @Override
    public List<Long> queryUserRoleIds(Long userId) {
        List<Long> userRoleIds = adminUserRoleService.lambdaQuery()
                .select(AdminUserRole::getRoleId)
                .eq(AdminUserRole::getUserId, userId)
                .list()
                .stream()
                .map(AdminUserRole::getRoleId)
                .collect(Collectors.toList());
        // 获取部门角色 ID 列表并加入用户角色 ID 列表
        List<Long> deptRoleIds = adminDeptRoleService.lambdaQuery()
                .select(AdminDeptRole::getRoleId)
                .eq(AdminDeptRole::getDeptId, getById(userId).getDeptId())
                .list()
                .stream()
                .map(AdminDeptRole::getRoleId)
                .collect(Collectors.toList());
        userRoleIds.addAll(deptRoleIds);
        // 返回去重后的用户角色 ID 列表
        return userRoleIds.stream().distinct().collect(Collectors.toList());

    }

    /**
     * 通讯录查询
     *
     * @param userBookBO data
     * @return
     */
    @Override
    public BasePage<UserBookVO> queryListName(UserBookBO userBookBO) {
        userBookBO.setUserId(UserUtil.getUserId());
        return getBaseMapper().queryListName(userBookBO.parse(), userBookBO);
    }

    private static final List<Character> BASE_CHAR = Arrays.asList('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');

    /**
     * 查询组织架构下员工信息
     *
     * @return 组织架构信息
     */
    @Override
    public AdminOrganizationVO queryOrganizationInfo() {
        //0.组织对象：包含部门，员工，部门与员工关系
        AdminOrganizationVO adminOrganizationVO = new AdminOrganizationVO();
        //1.部门
        LambdaQueryWrapper<AdminDept> deptQueryWrapper = new LambdaQueryWrapper<>();
        deptQueryWrapper.select(AdminDept::getDeptId, AdminDept::getParentId, AdminDept::getName);
        List<AdminDeptVO> deptVOList = adminDeptService.list(deptQueryWrapper).stream().map(data -> BeanUtil.copyProperties(data, AdminDeptVO.class)).collect(Collectors.toList());
        Long logicDeptId = adminDeptService.getLogicDeptId();
        List<AdminDeptVO> childList = RecursionUtil.getChildListTree(deptVOList, "parentId", logicDeptId, "deptId", "children", AdminDeptVO.class);
        AdminDept currentDept = adminDeptService.getById(logicDeptId);
        AdminDeptVO root = new AdminDeptVO(currentDept);
        root.setChildren(childList);
        adminOrganizationVO.setDeptList(Lists.newArrayList(root));
        //2.员工
        List<Long> deptIds = getDeptIdByRecursion(Lists.newArrayList(root));
        LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(AdminUser::getUserId, AdminUser::getImg, AdminUser::getRealname, AdminUser::getDeptId, AdminUser::getStatus);
        queryWrapper.in(ObjectUtils.isNotEmpty(deptIds),AdminUser::getDeptId,deptIds);
        //2.1将用户分组，禁用的员工只在禁用员工列表显示
        Map<Integer, List<SimpleUser>> collect = this.list(queryWrapper).stream().map(data -> BeanUtil.copyProperties(data, SimpleUser.class)).collect(Collectors.groupingBy(SimpleUser::getStatus));
        adminOrganizationVO.setDisableUserList(Optional.ofNullable(collect.get(0)).orElse(Collections.emptyList()));
        //2.2未激活员工和正常员工相同的处理逻辑
        List<SimpleUser> userList = collect.get(1);
        userList.addAll(Optional.ofNullable(collect.get(2)).orElse(Collections.emptyList()));
        //2.3处理字母排序逻辑
        Map<Character, List<SimpleUser>> userMap = userList.stream().collect(Collectors.groupingBy(data -> {
            String realName = data.getRealname();
            char character = realName.charAt(0);
            if (PinyinUtil.isChinese(character)) {
                //转为大写字母
                return (char) (PinyinUtil.getFirstLetter(character) - 32);
            } else if (BASE_CHAR.contains(character)) {
                char start = 'a';
                char ending = 'z';
                if (character >= start && character <= ending) {
                    character -= 32;
                }
                return character;
            } else {
                // ^的ASCII码为94，大于A-Z，先使用这个，再替换为 #
                return '^';
            }
        }));
        // 2.4 ^的ASCII码为94，大于A-Z，先使用这个，再替换为 #
        LinkedHashMap<Character, List<SimpleUser>> linkedHashMap = new LinkedHashMap<>(userMap);
        linkedHashMap.put('#', Optional.ofNullable(linkedHashMap.remove('^')).orElse(Collections.emptyList()));
        adminOrganizationVO.setUserMap(linkedHashMap);

        Map<Long, List<SimpleUser>> deptMap = userList.stream().filter(ObjectUtil::isNotEmpty).collect(Collectors.groupingBy(SimpleUser::getDeptId));
        //3.处理部门与员工的关系
        for (AdminDeptVO deptVO : deptVOList) {
            Long deptId = deptVO.getDeptId();
            if (deptMap.containsKey(deptId)) {
                deptVO.setUserList(deptMap.get(deptId).stream().peek(data -> data.setDeptName(deptVO.getName())).collect(Collectors.toList()));
            }
        }
        return adminOrganizationVO;
    }

    private List<Long> getDeptIdByRecursion(List<AdminDeptVO> adminDeptVOS){
        List<Long>deptIds = Lists.newArrayList();
        for (AdminDeptVO adminDeptVO : adminDeptVOS) {
            deptIds.add(adminDeptVO.getDeptId());
            if(ObjectUtils.isNotEmpty(adminDeptVO.getChildren())){
                List<Long> childrenDeptIds =  getDeptIdByRecursion(adminDeptVO.getChildren());
                deptIds.addAll(childrenDeptIds);
            }else{
                continue;
            }
        }
        return deptIds;
    }

    /**
     * 切换关注状态
     *
     * @param userId 用户ID 0代表全部
     * @return
     */
    @Override
    public void attention(Long userId) {
        QueryWrapper<AdminAttention> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("be_user_id", userId);
        long count = adminAttentionService.count(queryWrapper);
        if (count > 0) {
            adminAttentionService.remove(queryWrapper);
        } else {
            AdminAttention attention = new AdminAttention();
            attention.setBeUserId(userId);
            attention.setAttentionUserId(UserUtil.getUserId());
            adminAttentionService.save(attention);
        }
    }

    /**
     * 根据ids查询用户信息
     *
     * @param ids id列表
     * @return data
     */
    @Override
    public List<SimpleUser> queryUserByIds(List<Long> ids) {
        if (ids.isEmpty()) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(AdminUser::getUserId, AdminUser::getImg, AdminUser::getRealname).in(AdminUser::getUserId, ids);
        List<AdminUser> list = list(queryWrapper);
        return list.stream().map(obj -> BeanUtil.copyProperties(obj, SimpleUser.class)).collect(Collectors.toList());
    }

    @Override
    public List<Long> queryNormalUserByIds(List<Long> ids) {
        if (ids.isEmpty()) {
            return ids;
        }
        LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(AdminUser::getUserId)
                .in(AdminUser::getUserId, ids)
                .eq(AdminUser::getStatus, 1);

        List<Long> list = listObjs(queryWrapper, TypeUtils::castToLong);
        if (CollUtil.isNotEmpty(list)) {
            ids.retainAll(list);
        } else {
            ids = list;
        }
        return ids;
    }

    /**
     * 根据部门ids查询用户列表
     *
     * @param ids id列表
     * @return data
     */
    @Override
    public List<Long> queryUserByDeptIds(List<Long> ids) {
        if (ids.isEmpty()) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(AdminUser::getUserId);
        if (ids.size() > 1) {
            queryWrapper.in(AdminUser::getDeptId, ids);
        } else {
            queryWrapper.eq(AdminUser::getDeptId, ids.get(0));
        }
        return listObjs(queryWrapper, obj -> Long.valueOf(obj.toString()));
    }

    @Override
    public List<SimpleUser> queryListByDeptIds(List<Long> deptIds) {
        if (CollUtil.isEmpty(deptIds)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(AdminUser::getUserId, AdminUser::getUsername, AdminUser::getDeptId, AdminUser::getRealname);
        queryWrapper.in(AdminUser::getDeptId, deptIds);
        List<AdminUser> users = list(queryWrapper);
        return users.stream().map(u -> {
            SimpleUser user = new SimpleUser();
            user.setUserId(u.getUserId());
            user.setRealname(u.getRealname());
            user.setDeptId(u.getDeptId());
            user.setDeptName(u.getDeptName());
            return user;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<OperationLog> hrmAddUser(HrmAddUserBO hrmAddUserBO) {
        Result<Set<HrmEmployee>> listResult = hrmService.queryEmployeeListByIds(hrmAddUserBO.getEmployeeIds());
        Set<HrmEmployee> employeeList = listResult.getData();
        List<OperationLog> operationLogList = new ArrayList<>();
        for (HrmEmployee hrmEmployee : employeeList) {
            AdminUserVO adminUserVO = new AdminUserVO();
            adminUserVO.setRealname(hrmEmployee.getEmployeeName());
            adminUserVO.setUsername(hrmEmployee.getMobile());
            adminUserVO.setSex(hrmEmployee.getSex());
            adminUserVO.setMobile(hrmEmployee.getMobile());
            adminUserVO.setPassword(hrmAddUserBO.getPassword());
            adminUserVO.setEmail(hrmEmployee.getEmail());
            adminUserVO.setDeptId(hrmAddUserBO.getDeptId());
            adminUserVO.setParentId(hrmAddUserBO.getParentId());
            adminUserVO.setRoleId(hrmAddUserBO.getRoleId());
            adminUserVO.setPost(hrmEmployee.getPost());
            JSONObject jsonObject = addUser(adminUserVO);
            operationLogList.add((OperationLog) jsonObject.get("operationLog"));
        }
        return operationLogList;
    }

    @Override
    public DeptUserListVO queryDeptUserList(Long deptId, boolean isAllUser) {
        DeptUserListVO deptUserListVO = new DeptUserListVO();
        List<DeptVO> deptList = adminDeptService.queryDeptUserList();
        createTree(deptId, deptList);
        List<HrmSimpleUserVO> userList;
        if (isAllUser) {
            userList = getBaseMapper().querySimpleUserByDeptId(deptId);
        } else {
            userList = getBaseMapper().querySimpleUserByDeptIdAndExamine(deptId);
        }
        List<DeptVO> collect = deptList.stream().filter(dept -> dept.getParentId().equals(deptId)).collect(Collectors.toList());
        deptUserListVO.setDeptList(collect);
        deptUserListVO.setUserList(userList);
        return deptUserListVO;
    }

    private List<DeptVO> createTree(Long pid, List<DeptVO> deptList) {
        List<DeptVO> treeDept = new ArrayList<>();
        for (DeptVO dept : deptList) {
            if (ObjectUtil.equal(pid, dept.getParentId())) {
                treeDept.add(dept);
                List<DeptVO> children = createTree(dept.getDeptId(), deptList);
                if (CollUtil.isNotEmpty(children)) {
                    for (DeptVO child : children) {
                        dept.setAllNum(dept.getAllNum() + child.getAllNum());
                    }
                    dept.setHasChildren(1);
                } else {
                    dept.setHasChildren(0);
                }
            }
        }
        return treeDept;
    }

    @Override
    public Set<HrmSimpleUserVO> queryDeptUserListByHrm(DeptUserListByHrmBO deptUserListByHrmBO) {
        Set<HrmSimpleUserVO> userVOSet = new HashSet<>();
        if (CollUtil.isNotEmpty(deptUserListByHrmBO.getDeptIdList())) {
            List<AdminUser> userList = findChildUserList(deptUserListByHrmBO.getDeptIdList());
            List<HrmSimpleUserVO> hrmSimpleUserVOS = TransferUtil.transferList(userList, HrmSimpleUserVO.class);
            userVOSet.addAll(hrmSimpleUserVOS);
        }
        if (CollUtil.isNotEmpty(deptUserListByHrmBO.getUserIdList())) {
            List<AdminUser> userList = query().select("user_id", "realname", "img", "sex", "username as mobile", "post").in("user_id", deptUserListByHrmBO.getUserIdList())
                    .ne("status", 0).list();
            List<HrmSimpleUserVO> hrmSimpleUserVOS = TransferUtil.transferList(userList, HrmSimpleUserVO.class);
            userVOSet.addAll(hrmSimpleUserVOS);
        }
        return userVOSet;
    }

    private List<AdminUser> findChildUserList(List<Long> deptIds) {
        List<AdminUser> empList = new ArrayList<>();
        for (Long deptId : deptIds) {
            List<AdminUser> list = query().select("user_id", "realname", "img", "sex", "username as mobile", "post").eq("dept_id", deptId).ne("status", 0).list();
            empList.addAll(list);
            List<AdminDept> childList = adminDeptService.lambdaQuery().select(AdminDept::getDeptId).eq(AdminDept::getParentId, deptId).list();
            if (CollUtil.isNotEmpty(childList)) {
                List<Long> childDeptIds = childList.stream().map(AdminDept::getDeptId).collect(Collectors.toList());
                empList.addAll(findChildUserList(childDeptIds));
            }
        }
        return empList;
    }

    @Override
    public List<Long> queryUserIdByRealName(List<String> realNames) {
        if (CollUtil.isEmpty(realNames)) {
            return new ArrayList<>();
        }
        return lambdaQuery().select(AdminUser::getUserId)
                .in(AdminUser::getRealname, realNames)
                .list().stream().map(AdminUser::getUserId).collect(Collectors.toList());
    }

    @Override
    public Long queryUserIdByUserNameAndCompanyId(String username) {
        return getBaseMapper().queryUserIdByUserNameAndCompanyId(username);
    }

    @Override
    public UserInfo queryLoginUserInfo(Long userId) {
        List<UserInfo> userInfoList = getBaseMapper().queryLoginUserInfo(userId);
        if (userInfoList.isEmpty()) {
            throw new CrmException(AdminCodeEnum.ADMIN_USER_NOT_EXIST_ERROR);
        }
        UserInfo userInfo = userInfoList.get(0);
        AdminRole role = adminRoleService.lambdaQuery().eq(AdminRole::getRemark, "admin").one();
        if (BeanUtil.isNotEmpty(role)) {
            userInfo.setSuperRoleId(role.getRoleId());
        }
        userInfo.setRoles(queryUserRoleIds(userInfo.getUserId()));
        return userInfo;
    }

    @Override
    public List<AdminUser> queryByUserName(String phone) {
        return getBaseMapper().queryByUserName(phone);
    }

    /**
     * 查询所有员工
     *
     * @return
     */
    @Override
    public List<UserInfo> queryAllUserInfoList() {
        if (UserUtil.getUser() == null ) {
            return Collections.emptyList();
        }
        List<AdminUser> adminUserList = lambdaQuery().list();
        for (AdminUser user : adminUserList) {
            String deptName = UserCacheUtil.getDeptName(user.getDeptId());
            user.setDeptName(deptName);
        }
        List<AdminUserRole> userRoles = adminUserRoleService.query().list();


        List<AdminDeptRole> deptRoles = adminDeptRoleService.query().list();

        Map<Long, List<AdminUserRole>> longListMap = userRoles.stream().collect(Collectors.groupingBy(AdminUserRole::getUserId));
        Map<Long, List<AdminDeptRole>> deptIdRoles = deptRoles.stream().collect(Collectors.groupingBy(AdminDeptRole::getDeptId));

        List<UserInfo> userInfoList = adminUserList.stream().map(user -> BeanUtil.copyProperties(user, UserInfo.class)).collect(Collectors.toList());
        for (UserInfo userInfo : userInfoList) {
            ArrayList<Long> rolesList = new ArrayList<>();

            List<AdminUserRole> roleList = longListMap.get(userInfo.getUserId());
            if (roleList != null) {
                List<Long> collect = roleList.stream().map(AdminUserRole::getRoleId).collect(Collectors.toList());
                rolesList.addAll(collect);
            }

            List<AdminDeptRole> deptRoleList = deptIdRoles.get(userInfo.getDeptId());
            if (deptRoleList != null) {
                List<Long> collect = deptRoleList.stream().map(AdminDeptRole::getRoleId).collect(Collectors.toList());
                rolesList.addAll(collect);
            }
            userInfo.setRoles(rolesList.stream().distinct().collect(Collectors.toList()));
        }
        return userInfoList;
    }

    @Override
    public void downloadExcel(HttpServletResponse response) {
        List<JSONObject> list = queryField();
        ExcelParseUtil.importExcel(new ExcelParseUtil.ExcelParseService() {
            @Override
            public String getExcelName() {
                return "员工";
            }

            @Override
            public String getMergeContent(String module) {
                return "注意事项：\n" +
                        "1、表头标“*”的红色字体为必填项\n" +
                        "2、手机号：目前只支持中国大陆的11位手机号码；且手机号不允许重复\n" +
                        "3、登录密码：密码由6-20位字母、数字组成\n" +
                        "4、部门：上下级部门间用\"/\"隔开，且从最上级部门开始，例如“上海分公司/市场部/市场一部”。如出现相同的部门，则默认导入组织架构中顺序靠前的部门\n";
            }
        }, list, response, "user");
    }

    @Override
    public UserInfoVO queryUserDeptOrRoleInfo(UserInfoRequestBO requestBO) {
        UserInfoVO infoVO = new UserInfoVO();
        if (CollUtil.isNotEmpty(requestBO.getUserIds())) {
            List<AdminUser> adminUsers = lambdaQuery()
                    .select(AdminUser::getUserId, AdminUser::getRealname, AdminUser::getImg)
                    .in(AdminUser::getUserId, requestBO.getUserIds()).list();
            List<SimpleUser> simpleUsers = adminUsers.stream().map(a -> {
                SimpleUser user = new SimpleUser();
                user.setUserId(a.getUserId());
                user.setRealname(a.getRealname());
                user.setImg(a.getImg());
                return user;
            }).collect(Collectors.toList());
            infoVO.setUsers(simpleUsers);
        }
        if (CollUtil.isNotEmpty(requestBO.getDeptIds())) {
            List<AdminDept> adminDepts = adminDeptService.lambdaQuery()
                    .select(AdminDept::getDeptId, AdminDept::getName)
                    .in(AdminDept::getDeptId, requestBO.getDeptIds()).list();
            List<SimpleDept> simpleDepts = adminDepts.stream().map(a -> {
                SimpleDept simpleDept = new SimpleDept();
                simpleDept.setId(a.getDeptId());
                simpleDept.setName(a.getName());
                return simpleDept;
            }).collect(Collectors.toList());
            infoVO.setDepts(simpleDepts);
        }
        if (CollUtil.isNotEmpty(requestBO.getRoleIds())) {
            List<AdminRole> adminRoles = adminRoleService
                    .lambdaQuery().select(AdminRole::getRoleId, AdminRole::getRoleName)
                    .in(AdminRole::getRoleId, requestBO.getRoleIds()).list();
            List<Map<String, Object>> roles = adminRoles.stream().map(a -> {
                Map<String, Object> role = new HashMap<>();
                role.put("roleId", a.getRoleId());
                role.put("roleName", a.getRoleName());
                return role;
            }).collect(Collectors.toList());
            infoVO.setRoles(roles);
        }
        return infoVO;
    }

    private List<JSONObject> queryField() {
        List<JSONObject> list = new ArrayList<>();
        list.add(queryField("username", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "手机号", 1));
        list.add(queryField("password", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "登录密码", 1));
        list.add(queryField("realname", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "姓名", 1));
        list.add(queryField("sex", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "性别", 0));
        list.add(queryField("email", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "邮箱", 0));
        list.add(queryField("deptName", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "部门", 1));
        list.add(queryField("post", FieldEnum.TEXT.getFormType(), FieldEnum.TEXT.getType(), "岗位", 0));
        return list;
    }

    private JSONObject queryField(String fieldName, String formType, Integer type, String name, Integer isNull) {
        JSONObject json = new JSONObject();
        json.fluentPut("fieldName", fieldName)
                .fluentPut("formType", formType)
                .fluentPut("type", type)
                .fluentPut("name", name).fluentPut("isNull", isNull);
        return json;
    }

    @Override
    public List<UserInfo> queryParentByLevel(AdminUserQueryBO queryBO) {
        List<UserInfo> result = new ArrayList<>();
        List<UserInfo> users = queryAllUserInfoList();
        List<Integer> levels = queryBO.getLevels();
        CollUtil.sort(levels, (Comparator.comparingInt(o -> o)));
        for (Integer level : levels) {
            UserInfo userInfo = this.queryParentByLevel(users, queryBO.getUserId(), level);
            if (ObjectUtil.isNotNull(userInfo)) {
                result.add(userInfo);
            }
        }
        return result;
    }

    private UserInfo queryParentByLevel(List<UserInfo> users, Long userId, Integer level) {
        if (level <= 0) {
            return null;
        }
        level--;
        UserInfo currentUser = users.stream().filter(userInfo -> ObjectUtil.equal(userId, userInfo.getUserId())).findFirst().orElse(null);
        if (ObjectUtil.isNotNull(currentUser)) {
            Long parentId = currentUser.getParentId();
            if (ObjectUtil.isNotNull(parentId) && ObjectUtil.notEqual(0, parentId)) {
                if (level == 0) {
                    return users.stream().filter(userInfo -> ObjectUtil.equal(parentId, userInfo.getUserId())).findFirst().orElse(null);
                } else {
                    return queryParentByLevel(users, parentId, level);
                }
            }
        }
        return null;
    }

    @Override
    public void clearUserCache(Long... userIds) {
        if (userIds == null) {
            return;
        }
        for (Long userId : userIds) {
            UserCacheUtil.removeUserCache(userId);
        }
    }


    @Override
    public SimpleUser bindingWxWorkUserId(String token, String wxUserId) {
        AdminUser one = lambdaQuery().eq(AdminUser::getWxUserId, wxUserId).one();
        if (one != null) {
            throw new CrmException(AdminCodeEnum.ADMIN_SCRM_WXCHAT_WORK_MOBILE_IN_USE_ERROR, one.getRealname());
        }
        AdminUser adminUser = getById(UserUtil.getUserId());
        adminUser.setWxUserId(wxUserId);
        adminUser.setIsBindingWork(1);
        updateById(adminUser);
        UserInfo user = UserUtil.getUser();
        user.setWxUserId(adminUser.getWxUserId());
        return BeanUtil.copyProperties(user, SimpleUser.class);
    }

    /**
     * 解绑企业微信根据用户ID
     *
     * @param userId
     */
    @Override
    public void unbindingWxWorkByUserId(Long userId) {
        AdminUser user = getById(userId);
        if (user == null) {
            throw new CrmException(AdminCodeEnum.ADMIN_USER_NOT_EXIST_ERROR);
        }
        lambdaUpdate().set(AdminUser::getIsBindingWork, 0).set(AdminUser::getWxUserId, null).eq(AdminUser::getUserId, userId).update();
    }

    /**
     * 导出
     *
     * @param response
     */
    @Override
    public void exportExcel(HttpServletResponse response, List<Long> userIds) {
        AdminUserBO adminUserBO = new AdminUserBO();
        adminUserBO.setUserIdList(userIds);
        adminUserBO.setPageType(0);
        List<AdminUserVO> dataList = queryUserList(adminUserBO).getList();
        List<Map<String, Object>> mapList = dataList.stream().map(BeanUtil::beanToMap).collect(Collectors.toList());

        List<ExcelParseUtil.ExcelDataEntity> headList = new ArrayList<>();
        headList.add(ExcelParseUtil.toEntity("status", "状态"));
        headList.add(ExcelParseUtil.toEntity("realname", "姓名"));
        headList.add(ExcelParseUtil.toEntity("username", "手机号（登录名）"));
        headList.add(ExcelParseUtil.toEntity("isBindingWork", "是否绑定企业微信"));
        headList.add(ExcelParseUtil.toEntity("sex", "性别"));
        headList.add(ExcelParseUtil.toEntity("email", "邮箱"));
        headList.add(ExcelParseUtil.toEntity("deptName", "主部门"));
        headList.add(ExcelParseUtil.toEntity("subsidiaryDeptName", "附属部门"));
        headList.add(ExcelParseUtil.toEntity("post", "岗位"));
        headList.add(ExcelParseUtil.toEntity("parentName", "直属上级"));
        headList.add(ExcelParseUtil.toEntity("roleName", "角色"));
        headList.add(ExcelParseUtil.toEntity("createTime", "创建时间"));
        ExcelParseUtil.exportExcel(mapList, new ExcelParseUtil.ExcelParseService() {
            @Override
            public ExcelParseUtil.DataFunc getFunc() {
                return (record, headMap) -> {
                    for (String fieldName : headMap.keySet()) {
                        if (ObjectUtil.equal(fieldName, "status")) {
                            if (ObjectUtil.equals(0, record.get(fieldName))) {
                                record.put("status", "禁用");
                            } else if (ObjectUtil.equals(1, record.get(fieldName))) {
                                record.put("status", "正常");
                            } else if (ObjectUtil.equals(2, record.get(fieldName))) {
                                record.put("status", "未激活");
                            }
                        }
                        if (ObjectUtil.equal(fieldName, "isBindingWork")) {
                            record.put("isBindingWork", Objects.equals(0, record.get("isBindingWork")) ? "未绑定" : "已绑定");
                        }
                        if (ObjectUtil.equal(fieldName, "sex")) {
                            if (ObjectUtil.equals(0, record.get(fieldName))) {
                                record.put("sex", "未选择");
                            } else if (ObjectUtil.equals(1, record.get(fieldName))) {
                                record.put("sex", "男");
                            } else if (ObjectUtil.equals(2, record.get(fieldName))) {
                                record.put("sex", "女");
                            }
                        }
                    }
                };
            }

            @Override
            public String getExcelName() {
                return "员工";
            }

            @Override
            public boolean isXlsx() {
                return true;
            }
        }, headList);
    }

    /**
     * 根据部门ids查询部门以及子部门用户列表
     *
     * @param ids id列表
     * @return data
     */
    @Override
    public List<Long> queryUserListByDeptIds(List<Long> ids) {
        if (ids.isEmpty()) {
            return new ArrayList<>();
        }
        //查询部门以及子部门
        Set<Long> deptIdList = new HashSet<>();
        List<Long> deptIds;
        for (Long id : ids) {
            deptIds = adminDeptService.queryChildDept(id);
            deptIdList.add(id);
            deptIdList.addAll(deptIds);
        }
        //查询部门以及子部门用户列表
        List<AdminUser> adminUserList = lambdaQuery().select(AdminUser::getUserId).in(AdminUser::getDeptId, deptIdList).list();
        return adminUserList.stream().distinct().map(AdminUser::getUserId).collect(Collectors.toList());
    }

    @Override
    public JSONObject resetPwdNotice() {
        JSONObject result = new JSONObject();
        AdminCompanySecuritySettingVO securitySettingVO = securitySettingService.queryByConfigType(1);
        Integer pwdValidPeriod = securitySettingVO.getPwdValidPeriod();
        boolean needReset = false;
        if (!ObjectUtil.equal(Integer.MAX_VALUE, pwdValidPeriod)) {
            UserInfo user = UserUtil.getUser();
            AdminUser adminUser = queryByUserName(user.getUsername()).get(0);
            LocalDateTime lastPwdUpdTime = adminUser.getLastPwdUpdTime();
            if (ObjectUtil.isNull(lastPwdUpdTime)) {
                lastPwdUpdTime = adminUser.getCreateTime();
            }
            LocalDateTime expireDateTime = lastPwdUpdTime.plusDays(Convert.toLong(pwdValidPeriod));
            if (expireDateTime.isAfter(LocalDateTime.now())) {
                needReset = true;
            }
        }
        result.put("needReset", needReset);
        return result;
    }

    @Override
    public JSONObject forceResetPwdNotice() {
        JSONObject result = new JSONObject();
        AdminUser adminUser = getById(UserUtil.getUserId());
        boolean needReset = false;
        if (ObjectUtil.isNotNull(adminUser) && ObjectUtil.equal(2, adminUser.getPwdUpdStatus()) && ObjectUtil.equal(UserUtil.getUser().getLoginType(),1)) {
            needReset = true;
        }
        result.put("needReset", needReset);
        return result;
    }

    @Override
    public JSONObject mobileSSOCheck() {
        JSONObject result = new JSONObject();
        AdminUser adminUser = getById(UserUtil.getUserId());
        LocalDateTime lastLoginTime = adminUser.getLastLoginTime();
        AdminCompanySecuritySettingVO securitySettingVO = securitySettingService.queryByConfigType(2);
        boolean flag = false;
        if (ObjectUtil.isNotNull(lastLoginTime)) {
            Integer maximumLoginFreeTime = securitySettingVO.getMaximumLoginFreeTime();
            Integer maximumLoginFreeTimeUnit = securitySettingVO.getMaximumLoginFreeTimeUnit();
            //now
            LocalDateTime now = LocalDateTime.now();
            if (ObjectUtil.equal(maximumLoginFreeTimeUnit, 1)) {
                //unit day
                if (lastLoginTime.plusDays(maximumLoginFreeTime).isAfter(now)) {
                    flag = true;
                }
            } else if (ObjectUtil.equal(maximumLoginFreeTimeUnit, 2)) {
                //unit hour
                if (lastLoginTime.plusHours(maximumLoginFreeTime).isAfter(now)) {
                    flag = true;
                }
            } else {
                //unit minute
                if (lastLoginTime.plusMinutes(maximumLoginFreeTime).isAfter(now)) {
                    flag = true;
                }
            }
        }
        result.put("checkResult", flag);
        return result;
    }

    @Override
    public void updateAdminUserLoginTime(String username) {
        lambdaUpdate().set(AdminUser::getLastLoginTime, LocalDateTime.now()).eq(AdminUser::getUsername, username).update();
    }

    @Override
    public Map<String, Object> getLastedLoginUser(String username) {
        return getBaseMapper().queryLastedLoginUser(username);
    }

    @Override
    public void batchUpdPasswordUpdStatus(List<AdminUser> users) {
        updateBatchById(users, 1000);
    }

    public static String handlePwdHistory(String oldPwd, String pwdHistory, String newPwd, AdminCompanySecuritySettingVO securitySettingVO) {
        if (StrUtil.isBlank(pwdHistory)) {
            pwdHistory = null;
        }
//        if (StrUtil.isNotBlank(pwdHistory)) {
        if (ObjectUtil.isNotNull(securitySettingVO) && ObjectUtil.isNotNull(securitySettingVO.getEnforcePwdHistory()) && securitySettingVO.getEnforcePwdHistory() > 0) {
            Integer enforcePwdHistory = securitySettingVO.getEnforcePwdHistory();
            List<String> pwdList = JSONObject.parseArray(pwdHistory, String.class);
            LinkedList<String> pwdLinkedList = new LinkedList<>(CollUtil.isNotEmpty(pwdList) ? pwdList : Collections.emptyList());
            if (pwdLinkedList.size() > 0 && pwdLinkedList.size() < 10) {
                pwdLinkedList.add(newPwd);
            } else if (pwdLinkedList.size() == 0) {
                pwdLinkedList.add(oldPwd);
                pwdLinkedList.add(newPwd);
            } else {
                pwdLinkedList.removeFirst();
                pwdLinkedList.add(newPwd);
            }
            return JSONObject.toJSONString(pwdLinkedList);

        }
        return null;
    }


    public static boolean checkPwdHistory(String pwdHistory, String oldPwd, String newPwd, AdminCompanySecuritySettingVO securitySettingVO) {
        if (ObjectUtil.isNotNull(securitySettingVO) && ObjectUtil.isNotNull(securitySettingVO.getEnforcePwdHistory()) && securitySettingVO.getEnforcePwdHistory() > 0) {
            if (StrUtil.isBlank(pwdHistory)) {
                return oldPwd.equals(newPwd);
            }
            List<String> pwdList = JSONObject.parseArray(pwdHistory, String.class);
            Integer enforcePwdHistory = securitySettingVO.getEnforcePwdHistory();
            int size = pwdList.size();
            if (enforcePwdHistory >= size) {
                return pwdHistory.contains(newPwd);
            } else {
                return pwdList.subList(size - enforcePwdHistory, size).contains(newPwd);
            }
        }
        return false;
    }

    /**
     * 设置企业超管等信息
     *
     * @param userInfoList 用户信息列表
     * @return data
     */
    private List<AdminUserInfo> setSuperInfo(List<AdminUserInfo> userInfoList) {
        userInfoList.forEach(userInfo -> {
            if(!Objects.equals(0L, userInfo.getParentId())){
                userInfo.setParentName(UserCacheUtil.getUserName(userInfo.getParentId()));
            }
            if(!Objects.equals(0L, userInfo.getDeptId())){
                userInfo.setDeptName(UserCacheUtil.getDeptName(userInfo.getDeptId()));
            }
            AdminUser adminUser = lambdaQuery().select(AdminUser::getUserId)
                    .one();
            userInfo.setSuperUserId(adminUser.getUserId());
            AdminRole role = adminRoleService.lambdaQuery().select(AdminRole::getRoleId).eq(AdminRole::getRemark, "admin").one();
            userInfo.setSuperRoleId(role.getRoleId());
        });
        return userInfoList;
    }
}
